﻿using System;
using System.Collections.Generic;
using System.Text;
using Tao.OpenGl;
using rkShared;


namespace rkClient
{
	//Renderer sınıfı client için gerekli tüm opengl çizim işlemlerini
	//yapan sınıf.Araziyi tankları ve diğer gerekli çizimler bu sınıf
	//içinde yapılacak.Böylece OpenGL kodları tek bir yerde bulunabilecek.
	class Renderer
	{
		Glu.GLUquadric tankQuadric ;
		rkShared.Texture explosionTexture1;
        rkShared.Texture explosionTexture2;


		public Renderer()
		{
			tankQuadric = Glu.gluNewQuadric();
			Glu.gluQuadricNormals(tankQuadric,Glu.GLU_SMOOTH);
			Glu.gluQuadricDrawStyle(tankQuadric,Glu.GLU_FILL);

            explosionTexture1 = new Texture("Data/explosion1.png", true);
            explosionTexture2 = new Texture("Data/explosion2.png", true);

		}
		//Call this method explicitly to cleanup resources used by the renderer
		public void CleanUp()
		{
			Glu.gluDeleteQuadric(tankQuadric);
            explosionTexture1.Destroy();
            explosionTexture2.Destroy();
		}
		//araziyi ve isteniyorsa normallerini ciz
		public void drawTerrain(Terrain terrain,bool showNormals)
		{
			int size = terrain.Size;
			int index = 0;
			Vector3[] vertices = terrain.Vertices;
			Vector3[] normals = terrain.Normals;
			int[] indices = terrain.Indices;
			Terrain.TerrainColor[] rockColors = terrain.RockColors;

			
			//draw grass layer
			terrain.GrassTexture.Bind();
			Gl.glColor4f(1.0f,1.0f,1.0f,1.0f);
			for(int i=0; i<size-1; ++i){
				Gl.glBegin(Gl.GL_TRIANGLE_STRIP);	
				
				for(int k=0; k<size; ++k){
					Gl.glNormal3f(normals[indices[index]].x,  normals[indices[index]].y, normals[indices[index]].z);
					Gl.glTexCoord2f(k,i+1);
					Gl.glVertex3f(vertices[indices[index]].x, vertices[indices[index]].y, vertices[indices[index]].z);
					index++;
					Gl.glNormal3f(normals[indices[index]].x,  normals[indices[index]].y, normals[indices[index]].z);
					Gl.glTexCoord2f(k,i);
					Gl.glVertex3f(vertices[indices[index]].x, vertices[indices[index]].y, vertices[indices[index]].z);
					index++;				
				}
				Gl.glEnd();
			}
			
			Gl.glDepthFunc(Gl.GL_EQUAL);
			Gl.glEnable(Gl.GL_BLEND);
			Gl.glBlendFunc(Gl.GL_SRC_ALPHA,Gl.GL_ONE_MINUS_SRC_ALPHA);

			//draw rock layer
			index = 0;
			terrain.RockTexture.Bind();
			
			for(int i=0; i<size-1; ++i){
				Gl.glBegin(Gl.GL_TRIANGLE_STRIP);	
				
				for(int k=0; k<size; ++k){
					Gl.glColor4f(rockColors[indices[index]].r,rockColors[indices[index]].g,rockColors[indices[index]].b,rockColors[indices[index]].a);
					Gl.glNormal3f(normals[indices[index]].x,  normals[indices[index]].y, normals[indices[index]].z);
					Gl.glTexCoord2f(k/2.0f,(i+1)/2.0f);
					Gl.glVertex3f(vertices[indices[index]].x, vertices[indices[index]].y, vertices[indices[index]].z);
					index++;
					Gl.glColor4f(rockColors[indices[index]].r,rockColors[indices[index]].g,rockColors[indices[index]].b,rockColors[indices[index]].a);
					Gl.glNormal3f(normals[indices[index]].x,  normals[indices[index]].y, normals[indices[index]].z);
					Gl.glTexCoord2f(k/2.0f,i/2.0f);
					Gl.glVertex3f(vertices[indices[index]].x, vertices[indices[index]].y, vertices[indices[index]].z);
					index++;				
				}
				Gl.glEnd();
			}

			Gl.glDepthFunc(Gl.GL_LEQUAL);
			Gl.glDisable(Gl.GL_BLEND);
			
			if(showNormals){
				Gl.glColor3f(1.0f,0.0f,0.0f);
				Gl.glBegin(Gl.GL_LINES);	
				index = 0;
				for(int i=0; i<size; ++i){
					
					
					for(int k=0; k<size; ++k){
						Gl.glVertex3f(vertices[index].x , 
									  vertices[index].y , 
									  vertices[index].z );
						
						Gl.glVertex3f(vertices[index].x + normals[index].x*10, 
									  vertices[index].y + normals[index].y*10, 
									  vertices[index].z + normals[index].z*10);
						index++;				
					}
					
				}
				Gl.glEnd();
			}
		}
		public void drawTank(Tank tank)
		{
            if (tank.Hitpoints > 0)
            {
                Gl.glPushMatrix();

                Gl.glTranslatef(tank.Position.x, tank.Position.y + 4.0f, tank.Position.z);

                Gl.glRotatef(90.0f, 1.0f, 0.0f, 0.0f);

                Gl.glColor3f(0.6f, 0.6f, 0.6f);
                Gl.glDisable(Gl.GL_TEXTURE_2D);
                //üst disk dövde
                Gl.glPushMatrix();
                Gl.glRotatef(180.0f, 1.0f, 0.0f, 0.0f);
                Glu.gluDisk(tankQuadric, 0.0f, 5.0f, 24, 1);
                Gl.glPopMatrix();

                //govde
                Glu.gluCylinder(tankQuadric, 5.0f, 5.0f, 3, 24, 1);

                //player rengini burda kullan
                //kabin
                Gl.glColor3fv(tank.getColor());
                Glu.gluSphere(tankQuadric, 3, 10, 10);

                //namlu
                Gl.glColor3f(0.6f, 0.6f, 0.6f);
                Gl.glPushMatrix();
                Gl.glTranslatef(0.0f, 0.0f, -1.0f);
                Gl.glRotatef(90.0f, 1.0f, 0.0f, 0.0f);
                Gl.glRotatef(tank.CanonRotation, 0.0f, 1.0f, 0.0f);
                Glu.gluCylinder(tankQuadric, 0.6f, 0.6f, 6, 24, 1);
                Gl.glPopMatrix();


                Gl.glPopMatrix();
            }


			//draw the tanks bullets after drawing the tank
			drawTankBullets(tank);
			
			Gl.glEnable(Gl.GL_TEXTURE_2D);

			for(int i=0; i< tank.Explosions.Count; ++i){
				drawBillboard((Billboard)tank.Explosions[i]);
			}
		}
		private void drawTankBullets(Tank tank)
		{
			Bullet bullet = null;
			for(int i=0; i<tank.bullets.Count; i++)
			{
				bullet = (Bullet)tank.bullets[i];
				Gl.glPushMatrix();
					Gl.glColor3fv(tank.getColor());
					Gl.glTranslatef(bullet.Position.x,bullet.Position.y,bullet.Position.z);
					Glu.gluSphere(tankQuadric,1.5f,4,4);				
				Gl.glPopMatrix();
			}
		}
		public void drawBillboard(Billboard billboard)
		{

			float[] modelview = new float[16];
			Gl.glGetFloatv(Gl.GL_MODELVIEW_MATRIX,modelview);
						
			Vector3 rightVec = new Vector3(modelview[0],modelview[4],modelview[8]);
			Vector3 upVec = new Vector3(modelview[1],modelview[5],modelview[9]);
			UMath.Normalize(ref rightVec,rightVec);
			UMath.Normalize(ref upVec,upVec);

			rightVec = rightVec * billboard.size * 0.5f;
			upVec = upVec * billboard.size * 0.5f;

			Vector3[] data = new Vector3[6];

			Vector3 vPos = billboard.position;

			data[0] = new Vector3(vPos - rightVec - upVec);
			data[1] = new Vector3(vPos - rightVec + upVec);
			data[2] = new Vector3(vPos + rightVec + upVec);
			data[3] = new Vector3(vPos + rightVec + upVec);
			data[4] = new Vector3(vPos + rightVec - upVec);
			data[5] = new Vector3(vPos - rightVec - upVec);
			
			float[] texCoords = new float[12];
			
			int currentTile = (int)billboard.fTile;

			texCoords[0] = currentTile/billboard.fTotal; texCoords[1] = 1.0f;
			texCoords[2] = currentTile/billboard.fTotal; texCoords[3] = 0.0f;
			texCoords[4] = (currentTile+1.0f)/billboard.fTotal; texCoords[5] = 0.0f;
			texCoords[6] = (currentTile+1.0f)/billboard.fTotal; texCoords[7] = 0.0f;
			texCoords[8] = (currentTile+1.0f)/billboard.fTotal; texCoords[9] = 1.0f;
			texCoords[10] = currentTile/billboard.fTotal; texCoords[11] = 1.0f;

			//bind billboard texture
            if (billboard.hit)
                explosionTexture1.Bind();
            else
                explosionTexture2.Bind();
			Gl.glEnable(Gl.GL_BLEND);
			Gl.glBlendFunc(Gl.GL_SRC_ALPHA,Gl.GL_ONE_MINUS_SRC_ALPHA);
			Gl.glEnable(Gl.GL_ALPHA_TEST);
			Gl.glAlphaFunc(Gl.GL_GREATER,0);

			Gl.glDisable(Gl.GL_CULL_FACE);
			Gl.glBegin(Gl.GL_TRIANGLES);

				for(int i=0;i<6;i++){
					Gl.glColor4f(1.0f,1.0f,1.0f,1.0f);
					Gl.glTexCoord2f(texCoords[i*2],texCoords[i*2+1]);
					Gl.glVertex3f(data[i].x,data[i].y,data[i].z);
				}


			Gl.glEnd();
			Gl.glEnable(Gl.GL_CULL_FACE);
			Gl.glDisable(Gl.GL_BLEND);
			Gl.glDisable(Gl.GL_ALPHA_TEST);
	
		}
	
	
	} 
   	
}
